import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { BaseService } from '@wwjCommon/base/base.service';
import { CacheService } from '@wwjCommon/cache/cache.service';
import { LoggingService } from '@wwjCommon/logging/logging.service';
import { UploadService } from '@wwjVendor/upload/upload.service';
import { PayService } from '@wwjVendor/pay/pay.service';
import { SmsService } from '@wwjVendor/sms/sms.service';
import { NoticeService } from '@wwjVendor/notice/notice.service';

@Injectable()
export class CoreTransferService extends BaseService<any> {
  private readonly logger = new Logger(CoreTransferService.name);

  constructor(
    @InjectRepository(Object)
    protected readonly repository: Repository<any>,
    private readonly cacheService: CacheService,
    private readonly configService: ConfigService,
    private readonly loggingService: LoggingService,
    private readonly uploadService: UploadService,
    private readonly payService: PayService,
    private readonly smsService: SmsService,
    private readonly noticeService: NoticeService,
  ) {
    super(repository);
  }

  /**
   * createRecord (原方法名: create)
   * 对应 PHP: CoreTransferService_core::create()
   * 逻辑类型: undefined - undefined
   * 注意: 为避免与BaseService方法冲突，已重命名
   */
  async createRecord(site_id: number, main_type: number, main_id: number, money: number, trade_type: number, remark: number) {
    // 基于PHP真实逻辑: create
    // PHP原文: $transfer_no = create_no();         $transfer_data = array(             'site_id' => $site_id,             'money' => $money,             'trade_type'...
const transfer_no = create_no(];
        const transfer_data = [
            site_id: site_id,
            money: money,
            trade_type: trade_type,
            transfer_no: transfer_no,
            main_id: main_id,
            main_type: main_type,
            transfer_status: TransferDict.WAIT,
            remark: remark,
        ];
        this.model.create(transfer_data);
        return transfer_no;
    }


    /**
     * 转账
     * @param int site_id
     * @param string transfer_no
     * @param string transfer_type
     * @param data
     * @return */
    async transfer(int site_id, string transfer_no, string transfer_type, data)
    {
        const transfer = this.findTransferByTransferNo(site_id, transfer_no);

        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.FAIL ))) throw new PayBusinessException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'];

        const transfer_account = data[ 'transfer_account' ] || '';
        const transfer_realname = data[ 'transfer_realname' ] || '';
        const transfer_data = [
            transfer_type: transfer_type,//转账方式
            transfer_realname: transfer_realname,//名称
            transfer_mobile: data[ 'transfer_mobile' ] || '',//手机号
            transfer_bank: data[ 'transfer_bank' ] || '',//转账银行
            transfer_account: transfer_account,//转账账号
            openid: data[ 'openid' ] || '',
            transfer_voucher: data[ 'transfer_voucher' ] || '',
            transfer_remark: data[ 'transfer_remark' ] || '',
            transfer_payee: data[ 'transfer_payee' ] || [),
            transfer_payment_code: data[ 'transfer_payment_code' ) || ''
        ];
        transfer.save(transfer_data);
        switch (transfer_type) {
            case TransferDict.WECHAT:
//                out_batch_no = create_no(];
                const transfer_account = data[ 'transfer_payee' ] || [);
                const scene_data = ( this.coreTransferSceneService ).getSceneInfoByType(site_id, transfer[ 'trade_type' )];
                //通过业务获取业务场景
                const temp_infos = scene_data[ 'infos' ] || [];//转账场景信息
                if (!!temp_infos)) {
                    const transfer_scene_report_infos = [];
                    foreach (temp_infos as key => item) {
                        transfer_scene_report_infos[] = [
                            info_type: key,
                            info_content: item
                        ;
  }
                transfer_account[ 'transfer_scene_report_infos' ] = transfer_scene_report_infos || [];//
                transfer_account[ 'user_recv_perception' ] = scene_data[ 'perception' ];//收款感知
                transfer_account[ 'transfer_scene_id' ] = scene_data[ 'scene_id' ];
//                transfer_account.out_batch_no = out_batch_no;
                break;
  }

  /**
   * transfer
   * 对应 PHP: CoreTransferService_core::transfer()
   * 逻辑类型: undefined - undefined
   */
  async transfer(site_id: any[], transfer_no: any[], transfer_type: any[], data: any[]) {
    // 基于PHP真实逻辑: transfer
    // PHP原文: $transfer = $this->findTransferByTransferNo($site_id, $transfer_no);          if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID...
const transfer = this.findTransferByTransferNo(site_id, transfer_no);

        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.FAIL ))) throw new PayBusinessException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'];

        const transfer_account = data[ 'transfer_account' ] || '';
        const transfer_realname = data[ 'transfer_realname' ] || '';
        const transfer_data = [
            transfer_type: transfer_type,//转账方式
            transfer_realname: transfer_realname,//名称
            transfer_mobile: data[ 'transfer_mobile' ] || '',//手机号
            transfer_bank: data[ 'transfer_bank' ] || '',//转账银行
            transfer_account: transfer_account,//转账账号
            openid: data[ 'openid' ] || '',
            transfer_voucher: data[ 'transfer_voucher' ] || '',
            transfer_remark: data[ 'transfer_remark' ] || '',
            transfer_payee: data[ 'transfer_payee' ] || [),
            transfer_payment_code: data[ 'transfer_payment_code' ) || ''
        ];
        transfer.save(transfer_data);
        switch (transfer_type) {
            case TransferDict.WECHAT:
//                out_batch_no = create_no(];
                const transfer_account = data[ 'transfer_payee' ] || [);
                const scene_data = ( this.coreTransferSceneService ).getSceneInfoByType(site_id, transfer[ 'trade_type' )];
                //通过业务获取业务场景
                const temp_infos = scene_data[ 'infos' ] || [];//转账场景信息
                if (!!temp_infos)) {
                    const transfer_scene_report_infos = [];
                    foreach (temp_infos as key => item) {
                        transfer_scene_report_infos[] = [
                            info_type: key,
                            info_content: item
                        ;
  }
                transfer_account[ 'transfer_scene_report_infos' ] = transfer_scene_report_infos || [];//
                transfer_account[ 'user_recv_perception' ] = scene_data[ 'perception' ];//收款感知
                transfer_account[ 'transfer_scene_id' ] = scene_data[ 'scene_id' ];
//                transfer_account.out_batch_no = out_batch_no;
                break;
  }

  /**
   * findTransferByTransferNo
   * 对应 PHP: CoreTransferService_core::findTransferByTransferNo()
   * 逻辑类型: undefined - undefined
   */
  async findTransferByTransferNo(site_id: number, transfer_no: number) {
    // 基于PHP真实逻辑: findTransferByTransferNo
    // PHP原文: $where = array(             [ 'site_id', '=', $site_id ],             [ 'transfer_no', '=', $transfer_no ]         );         return $this->model->whe...
const where = [
            [ 'site_id', '=', site_id ],
            [ 'transfer_no', '=', transfer_no )
        ];
        return this.model.where(where).findOrEmpty(];
    }


    /**
     * 转账回调
     * @param int site_id
     * @param string transfer_no
     * @param params
     * @return true
     */
    async transferNotify(int site_id, string transfer_no, params)
    {
        Log.write('transferNotify' . transfer_no];
        const transfer = this.findTransferByTransferNo(site_id, transfer_no);
        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'];
        const status = params[ 'status' ] || TransferDict.DEALING;
        Log.write('transferNotifyStatus' . status);
        switch (status) {
            case TransferDict.SUCCESS:
                Log.write('transferNotifyStatus1' . status];
                this.success(site_id, transfer_no];
                break;
            case TransferDict.FAIL:
                this.fail(site_id, transfer_no, params];
                break;
//            case TransferDict.DEALING:
//                this.dealing(site_id, transfer_no];
//                break;
            default:
                this.dealing(site_id, transfer_no, status);
                break;
  }

  /**
   * transferNotify
   * 对应 PHP: CoreTransferService_core::transferNotify()
   * 逻辑类型: undefined - undefined
   */
  async transferNotify(site_id: number, transfer_no: number, params: number) {
    // 基于PHP真实逻辑: transferNotify
    // PHP原文: Log::write('transferNotify' . $transfer_no);         $transfer = $this->findTransferByTransferNo($site_id, $transfer_no);         if ($transfer->isEmp...
Log.write('transferNotify' . transfer_no];
        const transfer = this.findTransferByTransferNo(site_id, transfer_no);
        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'];
        const status = params[ 'status' ] || TransferDict.DEALING;
        Log.write('transferNotifyStatus' . status);
        switch (status) {
            case TransferDict.SUCCESS:
                Log.write('transferNotifyStatus1' . status];
                this.success(site_id, transfer_no];
                break;
            case TransferDict.FAIL:
                this.fail(site_id, transfer_no, params];
                break;
//            case TransferDict.DEALING:
//                this.dealing(site_id, transfer_no];
//                break;
            default:
                this.dealing(site_id, transfer_no, status);
                break;
  }

  /**
   * success
   * 对应 PHP: CoreTransferService_core::success()
   * 逻辑类型: undefined - undefined
   */
  async success(site_id: any[], transfer_no: any[], params: any[]) {
    // 基于PHP真实逻辑: success
    // PHP原文: $transfer = $this->findTransferByTransferNo($site_id, $transfer_no);         Log::write('transferNotifyStatus2' . $transfer[ 'transfer_status' ]);    ...
const transfer = this.findTransferByTransferNo(site_id, transfer_no);
        Log.write('transferNotifyStatus2' . transfer[ 'transfer_status' )];
        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER');

        const trade_type = transfer.trade_type;
        const data = [
            transfer_time: time(),
            transfer_status: TransferDict.SUCCESS,
//            batch_id: params.batch_id || '',
//            out_batch_no: params.out_batch_no || '',
//            transfer_type: transfer_type,
        ];
        // 启动事务
        Db.startTrans(];
        try {
            transfer.save(data];
            Log.write('transferNotifyStatus3' . TransferDict.SUCCESS);
            const result = event('TransferSuccess', [ transfer_no: transfer_no, trade_type: trade_type, site_id: site_id )];
            if (!check_event_result(result)) {
                Db.rollback(];
                return false;
            }
            // 提交事务
            Db.commit();
            return true;
  }

  /**
   * fail
   * 对应 PHP: CoreTransferService_core::fail()
   * 逻辑类型: undefined - undefined
   */
  async fail(site_id: any[], transfer_no: any[], params: any[]) {
    // 基于PHP真实逻辑: fail
    // PHP原文: $transfer = $this->findTransferByTransferNo($site_id, $transfer_no);          if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID...
const transfer = this.findTransferByTransferNo(site_id, transfer_no);

        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER');
        const data = [
            transfer_time: time(),
            transfer_status: TransferDict.FAIL,
            transfer_fail_reason: params[ 'reason' ] || ''
        ];
        //允许修改的值

        transfer.save(data);
        return true;
    }


    async check(int site_id, data)
    {
        const transfer_no = data[ 'transfer_no' ];
        const transfer = this.findTransferByTransferNo(site_id, transfer_no);
        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验

        //查询第三方支付单据
        const transfer_info = this.pay_event.init(site_id, 'transfer', transfer.transfer_type).getTransfer(transfer_no, transfer[ 'out_batch_no' ) || ''];
        if (!transfer_info)) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];//查询不到转账信息
        const status = transfer_info[ 'status' );
        switch (status) {
            case TransferDict.SUCCESS:
                this.success(site_id, transfer_no];
                break;

            case TransferDict.FAIL:
                this.fail(site_id, transfer_no];
                break;
//            case TransferDict.DEALING:
            default:
                this.dealing(site_id, transfer_no, status);
                break;
  }

  /**
   * check
   * 对应 PHP: CoreTransferService_core::check()
   * 逻辑类型: undefined - undefined
   */
  async check(site_id: any[], data: any[]) {
    // 基于PHP真实逻辑: check
    // PHP原文: $transfer_no = $data[ 'transfer_no' ];         $transfer = $this->findTransferByTransferNo($site_id, $transfer_no);         if ($transfer->isEmpty()) ...
const transfer_no = data[ 'transfer_no' ];
        const transfer = this.findTransferByTransferNo(site_id, transfer_no);
        if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
        if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验

        //查询第三方支付单据
        const transfer_info = this.pay_event.init(site_id, 'transfer', transfer.transfer_type).getTransfer(transfer_no, transfer[ 'out_batch_no' ) || ''];
        if (!transfer_info)) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];//查询不到转账信息
        const status = transfer_info[ 'status' );
        switch (status) {
            case TransferDict.SUCCESS:
                this.success(site_id, transfer_no];
                break;

            case TransferDict.FAIL:
                this.fail(site_id, transfer_no];
                break;
//            case TransferDict.DEALING:
            default:
                this.dealing(site_id, transfer_no, status);
                break;
  }

  /**
   * dealing
   * 对应 PHP: CoreTransferService_core::dealing()
   * 逻辑类型: undefined - undefined
   */
  async dealing(site_id: number, transfer_no: number, status: number) {
    // 基于PHP真实逻辑: dealing
    // PHP原文: $this->model->where([             [ 'site_id', '=', $site_id ],             [ 'transfer_no', '=', $transfer_no ]         ])->update(             [ // ...
this.model.where([
            [ 'site_id', '=', site_id ],
            [ 'transfer_no', '=', transfer_no )
        )).update(
            [
//                transfer_status: TransferDict.DEALING,
                transfer_status: status,
            )
        ];
        return true;
    }

    /**
     * 用户确认转账信息
     * @param int site_id
     * @param string transfer_no
     * @param string channel
     * @param data
     * @return void
     */
//    async confirm(int site_id, string transfer_no, string channel, data ){
//        transfer_no = data.transfer_no;
//        transfer = this.findTransferByTransferNo(site_id, transfer_no);
//        if (transfer.transfer_type == TransferDict.WECHAT) {
//            //todo 判断微信转账是否已经超时
//
//            //todo 判断转账的主体授权信息是否一致
//            transfer_payee = transfer.transfer_payee;
//            transfer_open_id = transfer_payee.open_id;
//            open_id = data.open_id;
//
//
  }

  /**
   * confirm
   * 对应 PHP: CoreTransferService_core::confirm()
   * 逻辑类型: undefined - undefined
   */
  async confirm(site_id: any[], transfer_no: any[], channel: any[], data: any[]) {
    // 基于PHP真实逻辑: confirm
    // PHP原文: //        $transfer_no = $data['transfer_no']; //        $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); //        if($transfer['...
//        transfer_no = data.transfer_no;
//        transfer = this.findTransferByTransferNo(site_id, transfer_no);
//        if (transfer.transfer_type == TransferDict.WECHAT) {
//            //todo 判断微信转账是否已经超时
//
//            //todo 判断转账的主体授权信息是否一致
//            transfer_payee = transfer.transfer_payee;
//            transfer_open_id = transfer_payee.open_id;
//            open_id = data.open_id;
//
//
  }

  /**
   * cancel
   * 对应 PHP: CoreTransferService_core::cancel()
   * 逻辑类型: undefined - undefined
   */
  async cancel(site_id: number, transfer_no: number) {
    // 基于PHP真实逻辑: cancel
    // PHP原文: try {             $transfer = $this->findTransferByTransferNo($site_id, $transfer_no);             if ($transfer->isEmpty()) throw new PayException('T...
try {
            const transfer = this.findTransferByTransferNo(site_id, transfer_no);
            if (transfer.isEmpty()) throw new PayBusinessException('TRANSFER_ORDER_INVALID'];
            if (!in_[transfer[ 'transfer_status' ), [ TransferDict.WAIT, TransferDict.DEALING, TransferDict.FAIL, TransferDict.WAIT_USER, TransferDict.WAIT_USER_ING, TransferDict.FAIL_ING ))) throw new PayBusinessException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验

            //查询第三方支付单据
            const result = this.pay_event.init(site_id, 'transfer', transfer.transfer_type).transferCancel([
                transfer_no: transfer_no
            )];
            this.transferNotify(site_id, transfer_no, result);
            if (result[ 'status' ) == TransferDict.FAIL_ING) {//撤销中的话也要返回错误,不能让业务认为撤销成功了
                throw new PayBusinessException('TRANSFER_IS_FAILING');
            }
            return true;
  }
}
